﻿using System;
using System.Diagnostics;
using System.Linq;
using CommonBehaviors.Actions;
using Styx.CommonBot;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

using Action = Styx.TreeSharp.Action;

namespace PetBuddy.Helpers
{
    public class Seeker
    {
        #region Variables

        private static LocalPlayer Me = PetBuddy.Me;

        public static Stopwatch InteractTimer = new Stopwatch();
        
        #endregion

        //TODO: Make some filters to skip pointless critters

        public static WoWUnit _nextBattlePetCritter;
        public static WoWUnit NextBattlePetCritter
        {
            get
            {
                try
                {
                    if (_nextBattlePetCritter != null && !Blacklist.Contains(_nextBattlePetCritter.Guid) && !_nextBattlePetCritter.IsDead && _nextBattlePetCritter.IsPetBattleCritter)
                        return _nextBattlePetCritter;

                    var nextUnit = (from unit in ObjectManager.GetObjectsOfType<WoWUnit>(true, true)
                                    orderby unit.Distance ascending

                                    where !Blacklist.Contains(unit.Guid)
                                    where !unit.IsDead
                                    where unit.IsPetBattleCritter
                                    where unit.IsOutdoors

                                    select unit).FirstOrDefault();

                    if (nextUnit != null) 
                    {
                        _nextBattlePetCritter = nextUnit;
                        return nextUnit;
                    }
                    return null;
                }
                catch (Exception ex)
                {
                    PetBuddy.dlog("[Seeker] GetNextBattlePetCritter trow: \n{0}", ex.Message);
                    _nextBattlePetCritter = null;
                }
                return null;
            }
        }

        public static Composite FightSeeker()
        {
            return new PrioritySelector(

                // PVP Logic
                new Decorator(ret => PetBuddySettings.Instance.UsePVP,
                              new PrioritySelector(

                                  //TODO: Make some PVP handle behavior/logic

                                  new Decorator(ret => PVP.PVPMatchRready,
                                                new Sequence()),

                                  new Decorator(ret => !PVP.InMatchQueue,
                                                new Sequence()),

                                  new Decorator(ret => PetBuddySettings.Instance.SeekWhilePVP,
                                                new ActionAlwaysSucceed())
                                  )),

                // Outdoor Logic
                new Decorator(ret => NextBattlePetCritter == null,
                              new Sequence(
                                  PetBuddy.adlog("[Seeker] Seek next critter..."),
                                  Mover.PathMakerBehavior(),
                                  new Action(ret => PetBuddy.BotRunStatus.flag = PetBuddy.BotRunStatusEnum.IDLE)
                                  )),

                new Decorator(ret => NextBattlePetCritter != null,
                              new Sequence(
                                  new Action(ret => PetBuddy.dlog("[Seeker] Pursuing {0}", Me.GotTarget ? Me.CurrentTarget.Name : "next critter")),
                                  GoToInteractWithCritter()
                                  ))

                );
        }

        private static Composite GoToInteractWithCritter()
        {
            return new PrioritySelector(

                new Decorator(ret => Me.Location.Distance(NextBattlePetCritter.Location) > 12f,
                              new Sequence(

                                  new Action(ret => Mover.navSelector = Mover.NavSelector.CRITTER),
                                  Mover.MoveToTargetNavPoint()
                                  )),

                new Decorator(ret => Me.Location.Distance(NextBattlePetCritter.Location) <= 12f,
                              new PrioritySelector(

                                  new Decorator(ret => Me.Mounted, Mover.Dismounter()),

                                  new Decorator(ret => !Me.Mounted && !PetBattles.IsInBattle,
                                                new Sequence(
                                                    new Action(ret => PetBuddy.dlog("[Seeker] Interact with {0} at {1} from {2} yards",
                                                                                    NextBattlePetCritter.Name, NextBattlePetCritter.Location, Me.Location.Distance(NextBattlePetCritter.Location))),
                                                    new Action(ret => NextBattlePetCritter.Target()),
                                                    new Action(ret => WoWMovement.Face()),
                                                    new PrioritySelector(

                                                        new Decorator(ret => Me.Location.Distance(NextBattlePetCritter.Location) > 10,
                                                                      new Sequence(
                                                                          Mover.MoveToTargetNavPoint(),
                                                                          new Action(ret => { return RunStatus.Failure; })
                                                                          )),

                                                        new Decorator(ret => InteractTimer.IsRunning && InteractTimer.ElapsedMilliseconds >= PetBuddySettings.Instance.InteractTimer,
                                                                      new Sequence(
                                                                          new Action(ret => PetBuddy.dlog("[Seeker] Intercat with {0} at {1} fail, blacklist it on 30 sec",
                                                                                                          NextBattlePetCritter.Name, NextBattlePetCritter.Location)),
                                                                          new Action(ret => Blacklist.Add(NextBattlePetCritter.Guid, new TimeSpan(0, 0, 30))),
                                                                          new Action(ret => InteractTimer.Stop())
                                                                          )),

                                                        new Decorator(ret => Me.Location.Distance(NextBattlePetCritter.Location) <= 10,
                                                                      new Sequence(
                                                                          new Action(ret => NextBattlePetCritter.Interact()),
                                                                          new Decorator(ret => !InteractTimer.IsRunning,
                                                                                        new Action(ret => InteractTimer.Restart())),
                                                                          new Wait(1, ret => !PetBattles.IsInBattle, new ActionIdle()),
                                                                          new Action(ret => PetBuddy.BotRunStatus.flag = PetBuddy.BotRunStatusEnum.IDLE)
                                                                          ))
                                                        )
                                                    ))
                                  ))
                );
        }
    }
}
